package cn.ivicar.app.filter;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Properties;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.com.carsmart.util.configmanagement.ConfigUtil;

public class RequestParamPrintFilter implements Filter {

	private static transient final Logger LOGGER = LoggerFactory.getLogger(RequestParamPrintFilter.class);
	private static String environment = getInitParameter("env");

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
			throws IOException, ServletException {

		filterChain.doFilter(printRequestInfo(servletRequest), servletResponse);
		/*
		 * if ("test".equals(environment)) { } else {
		 * filterChain.doFilter(servletRequest, servletResponse); }
		 */
	}

	public ServletRequest printRequestInfo(ServletRequest servletRequest) throws IOException {
		ServletRequest requestWrapper = null;
		try {
			if (servletRequest instanceof HttpServletRequest) {
				HttpServletRequest request = (HttpServletRequest) servletRequest;
				requestWrapper = new MAPIHttpServletRequestWrapper(request);
			}

			HttpServletRequest request = (HttpServletRequest) requestWrapper;
			String requestURL = request.getRequestURL().toString();
			String method = request.getMethod();
			StringBuffer buffer = new StringBuffer();
			String queryString = request.getQueryString();
			if (StringUtils.isNotBlank(queryString)) {
				requestURL += "?" + queryString;
			}
			buffer.append("Request Info: \n");
			buffer.append("Request URL          : " + requestURL + "\n");
			buffer.append("Request Method       : " + method + "\n");
			buffer.append("Request Content-Type : " + request.getHeader("Content-Type") + "\n");

			String contentType = request.getHeader("Content-Type") == null ? "" : request.getHeader("Content-Type");
			if (!"multipart/form-data".contains(contentType) && "POST".equalsIgnoreCase(method)
					|| "PUT".equalsIgnoreCase(method)) {
				ServletInputStream inputStream = request.getInputStream();
				if (inputStream != null) {
					buffer.append("Request Parameters   : " + IOUtils.toString(inputStream) + "\n");
				}

			}
			LOGGER.info(buffer.toString());

		} catch (Exception e) {
			e.printStackTrace();
		}
		return requestWrapper;
	}

	public static String getInitParameter(String prop) {
		Properties props = new Properties();
		try {
			props = ConfigUtil.getConfigReader().getResourceAsProperties("../env.properties");
		} catch (IOException e) {
			System.out.print("can't find env.properties");
		}
		String result = props.getProperty(prop);
		return StringUtils.isBlank(result) ? "test" : result;
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

	}

	@Override
	public void destroy() {

	}

}

class MAPIHttpServletRequestWrapper extends HttpServletRequestWrapper {

	private final byte[] body;

	public MAPIHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
		super(request);
		body = readBytes(request.getReader(), "utf-8");
	}

	@Override
	public BufferedReader getReader() throws IOException {
		return new BufferedReader(new InputStreamReader(getInputStream()));
	}

	@Override
	public ServletInputStream getInputStream() throws IOException {
		final ByteArrayInputStream bais = new ByteArrayInputStream(body);
		return new ServletInputStream() {

			@Override
			public int read() throws IOException {
				return bais.read();
			}
		};
	}

	private byte[] readBytes(BufferedReader br, String encoding) throws IOException {
		String str = null, retStr = "";
		while ((str = br.readLine()) != null) {
			retStr += str;
		}
		if (StringUtils.isNotBlank(retStr)) {
			return retStr.getBytes(Charset.forName(encoding));
		}
		return new byte[1];
	}
}
